package cn.shop.front.config.redis;

import cn.hutool.core.convert.Convert;
import cn.shop.transcation.rechargerecord.entity.Record;
import cn.shop.transcation.rechargerecord.mapper.RecordMapper;
import cn.shop.utils.enums.TransactionState;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * @author jzw
 * @since 2021-12-13 17:31
 */
@Component
@Slf4j
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {

	@Resource
	private RecordMapper recordMapper;


	@Resource
	private RedissonClient redissonClient;


	public RedisKeyExpirationListener(RedisMessageListenerContainer container) {
		super(container);
	}

	/**
	 * 针对redis数据失效事件，进行数据处理
	 *
	 * @param message
	 * @param pattern
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void onMessage(Message message, byte[] pattern) {
		String key = message.toString();
		log.info("key：{} 已超时", key);
		if (key != null && key.startsWith("orderTR-")) {
			RLock lock = redissonClient.getLock("cancel-" + key);
			try {
				if (lock.tryLock(0, 30, TimeUnit.SECONDS)) {
					//截取订单号，查询订单，如果是未支付状态则取消订单
					String recordId = key.split("-")[1];
					Record record = new Record();
					record.setId(Convert.toLong(recordId));
					LambdaUpdateWrapper<Record> update = Wrappers.lambdaUpdate(record);
					update.set(Record::getState, TransactionState.CANCELLED).eq(Record::getState, TransactionState.PENDING_PAYMENT);
					recordMapper.update(record, update);
				}
			} catch (InterruptedException e) {
				TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

				log.error("redis 超时监听 获取锁 异常: {},key :{} ", e.getMessage(), key);
			} finally {
				if (lock.isLocked()) {
					lock.unlock();
				}
			}
		}
	}

}
